package com.huawei.bigdate.hbaseEs.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huawei.bigdate.hbaseEs.InitParameters;
import com.huawei.bigdate.hbaseEs.security.LoginUtil;
import org.apache.hadoop.yarn.proto.YarnProtos;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

@Component

public class ESSearch  {
    private static final Logger LOG = LoggerFactory.getLogger(ESSearch.class);
    private static String schema = "https";
    private static RestClientBuilder builder = null;
    private static RestClient restClient = null;
    private static List<String> esList;
    Properties properties = new Properties();
    /*加载application.properties配置文件参数*/
    public void esInit(){
        try {
            //配置ES集群信息并进行登录验证
            init();
            //获取客户端，连接Elasticsearch集群
            restClient = getRestClient();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public List getEsIndexList(String pagecodeflag, String cashclasscode,String version,String tablename) {
        try {

            //获取ES索引
            query(restClient, pagecodeflag, cashclasscode,version,tablename);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //在进行完Elasticsearch操作后，需要调用“restClient.close()”关闭所申请的资源。
        if (restClient != null) {
            try {
                restClient.close();
                LOG.info("Close the client successful in main.");
            } catch (Exception e1) {
                LOG.error("Close the client failed in main.", e1);
            }
        }
        return esList;
    }

    /**
     * 配置ES集群信息并进行登录验证
     **/
    public void init() throws Exception {
        //安全登录
        if ((InitParameters.isSecureMode).equals("true")) {
            String krb5ConfFile = ESSearch.class.getClassLoader().getResource(InitParameters.krb5File).getPath();
            System.setProperty("java.security.krb5.conf", krb5ConfFile);
            //配置jaas文件进行认证，并配置到JVM系统参数中
            String userKeytab = ESSearch.class.getClassLoader().getResource(InitParameters.userKeytabFile).getPath();
            LoginUtil.setJaasFile(InitParameters.userName, userKeytab);
            System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
            //添加ES安全指示
            System.setProperty("es.security.indication", "true");
        } else if ((InitParameters.isSecureMode).equals("false")) {
            System.setProperty("es.security.indication", "false");
            schema = "http";
        }
    }

    //************* 获取客户端，连接Elasticsearch集群 ************
    public RestClient getRestClient() throws Exception {
        List<HttpHost> hosts = new ArrayList<HttpHost>();
        String[] hostArray = InitParameters.esServerHost.split(",");

        for (String host : hostArray) {
            String[] ipPort = host.split(":");
            HttpHost hostNew = new HttpHost(ipPort[0], Integer.valueOf(ipPort[1]), schema);
            hosts.add(hostNew);
        }

        HttpHost[] httpHosts = hosts.toArray(new HttpHost[]{});
        builder = RestClient.builder(httpHosts);
        builder = builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
            @Override
            public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
                return requestConfigBuilder.setConnectTimeout(Integer.valueOf(InitParameters.ConnectTimeout)).setSocketTimeout(Integer.valueOf(InitParameters.SocketTimeout));
            }
        }).setMaxRetryTimeoutMillis(Integer.valueOf(InitParameters.MaxRetryTimeoutMillis));

        Header[] defaultHeaders = new Header[]{new BasicHeader("Accept", "application/json"),
                new BasicHeader("Content-type", "application/json")};
        builder.setDefaultHeaders(defaultHeaders);
        restClient = builder.build();
        restClient.setHosts(httpHosts);

        return restClient;
    }

    /**
     * 查询出ES索引
     **/
    public static void query(RestClient restClientTest,String pagecodeflag, String cashclasscode,String version,String tablename) {
        Response rsp = null;
        String jsonString = "{\"query\" : { \"bool\" : { \"should\" : [{ \"match\": { \"crownfontNumber\" : \""+pagecodeflag+"\" }},{ \"match\" : {\"edition\" : \""+cashclasscode+"\"}},{ \"match\": { \"coupon\" : \""+version+"\" }}],\"minimum_should_match\": 3}}}";

        Map<String, String> params = Collections.singletonMap("pretty", "true");
        HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);

        try {
            rsp = restClientTest.performRequest("GET", "/" + tablename + "/" + "_search", params, entity);
            if (HttpStatus.SC_OK == rsp.getStatusLine().getStatusCode()) {
                LOG.info("QueryData successful.");
            } else {
                LOG.error("QueryData failed.");
            }

            //得到查询出的结果
            String esResult = EntityUtils.toString(rsp.getEntity());
            LOG.info("QueryData response entity is : " + esResult);

            //进行json串的解析得到全部的esid
            JSONObject jsonObj = JSON.parseObject(esResult);
            String took = jsonObj.getString("took");
            String hitsStr = jsonObj.getString("hits");
            JSONObject hitsObj = JSON.parseObject(hitsStr);
            Long total = hitsObj.getLongValue("total");

            LOG.info("共耗费" + took + "毫秒, 全部数据有" + total + "条");
            //得到hits json数组
            JSONArray hitsArr = hitsObj.getJSONArray("hits");
            //构造esList
            esList = new ArrayList<String>();
            for (Object obj : hitsArr) {
                JSONObject esObj = (JSONObject) obj;
                esList.add(esObj.getString("_id"));
            }
        } catch (Exception e) {
            LOG.error("QueryData failed, exception occurred.", e);
        }
    }
}